/////////////////////////////////////////////     File     //////////////////////////////////////////////////
// Author: James Chen
// Filename: CUtilities.h
// Created: Friday, January 29, 2010 12:10:03 PM
/////////////////////////////////////////////////////////////////////////////////////////////////////////////

#pragma once

#include <windows.h> /* required for srand() */
#include <ctime>
#include <pdh.h>
#include <vector>

using namespace std;

#include <d3d10.h>
#include <d3dx10.h>
#include <dxerr.h>
#include <cassert>
#include <fstream>
#include <stdio.h>

#define FMODUSAGE 1

#define MOUSEWHEELCLICKSPEED	120
#define MAXZOOM					3000.0f
#define MINZOOM					10.0f
#define ZOOMINCREMENT			0.25f

//	The version of DirectInput to use.
#define DIRECTINPUT_VERSION 0x0800
#include <dinput.h>

#ifndef _USE_MATH_DEFINES
	#define _USE_MATH_DEFINES
#endif
#include <math.h>

#if FMODUSAGE
	#include <fmod.hpp>
#endif

#pragma comment(lib, "d3d10.lib")
#pragma comment(lib, "d3dx10.lib")

#pragma comment (lib, "dinput8.lib")
#pragma comment (lib, "dxguid.lib")
#pragma warning (disable : 4996)

#pragma comment(lib, "pdh.lib")

#ifndef _WIN32_WINNT
#define _WIN32_WINNT   0x0600 // Vista
#endif

/*---------------------------------------------------------------------------------------------------------*/
/*---------------------------------------------------------------------------------------------------------*/


//	Macro to safely Release COM Objects.
#ifndef SAFE_RELEASE
#define SAFE_RELEASE(p)		if (p) { p->Release(); p = NULL; }
#endif

//	MessageBox for Errors that occur within DirectInput.
#ifndef DIERRBOX
#define DIERRBOX(a)	{ MessageBox(m_hWnd, LPCWSTR(a), LPCWSTR("CDXInput Error"), MB_OK | MB_ICONEXCLAMATION); return false; }
#endif

// Enable extra D3D debugging in debug builds if using the debug DirectX runtime.  
// This makes D3D objects work well in the debugger watch window, but slows down 
// performance slightly.
#if defined(DEBUG) || defined(_DEBUG)
	#ifndef D3D_DEBUG_INFO
	#define D3D_DEBUG_INFO
	#endif
#endif

#if defined(DEBUG) || defined(_DEBUG)
#define _CRTDBG_MAP_ALLOC
#include <crtdbg.h>
#endif

#if defined(DEBUG) | defined(_DEBUG)
	#ifndef HR
	#define HR(x)                                              \
	{                                                          \
		HRESULT hr = (x);                                      \
		if(FAILED(hr))                                         \
		{                                                      \
			DXTrace(__FILE__, (DWORD)__LINE__, hr, L#x, true); \
		}                                                      \
	}
	#endif

#else
	#ifndef HR
	#define HR(x) (x)
	#endif
#endif 

#define ReleaseCOM(x) { if(x){ x->Release();x = 0; } }

/*---------------------------------------------------------------------------------------------------------*/
/*---------------------------------------------------------------------------------------------------------*/

//Globals

#define GOLDENRATIO 1.6180339887498948482

#define RANDMAX_SLOW 32767
#define RANDMAX_FASTI 32767
#define RANDMAX_FASTW 4294967295
#define RANDMAX_FASTMW 4294967295
#define RANDMAX_FASTSEED 4294967295

#define RadToDeg 57.29577951f
#define DegToRad 0.017453293f

enum RNDTYPE {FASTMW, FASTW, FASTI, FASTSEED, SLOW, SIZEOF};

enum PATHTYPE {LINEAR, SLERP, BEZIER};

enum FORCETYPE {GENERAL, GRAVITY, DRAG, THRUST, ROTATIONAL};

const D3DXCOLOR WHITE(1.0f, 1.0f, 1.0f, 1.0f);
const D3DXCOLOR BLACK(0.0f, 0.0f, 0.0f, 1.0f);
const D3DXCOLOR RED(1.0f, 0.0f, 0.0f, 1.0f);
const D3DXCOLOR GREEN(0.0f, 1.0f, 0.0f, 1.0f);
const D3DXCOLOR DARKGREEN(0.0f, 0.5f, 0.0f, 1.0f);
const D3DXCOLOR BLUE(0.0f, 0.0f, 1.0f, 1.0f);
const D3DXCOLOR YELLOW(1.0f, 1.0f, 0.0f, 1.0f);
const D3DXCOLOR CYAN(0.0f, 1.0f, 1.0f, 1.0f);
const D3DXCOLOR MAGENTA(1.0f, 0.0f, 1.0f, 1.0f);

const D3DXCOLOR BEACH_SAND(1.0f, 0.96f, 0.62f, 1.0f);
const D3DXCOLOR LIGHT_YELLOW_GREEN(0.48f, 0.77f, 0.46f, 1.0f);
const D3DXCOLOR DARK_YELLOW_GREEN(0.1f, 0.48f, 0.19f, 1.0f);
const D3DXCOLOR DARKBROWN(0.45f, 0.39f, 0.34f, 1.0f);
const D3DXCOLOR BROWN(0.50f, 0.25f, 0.0f, 1.0f);
const D3DXCOLOR TAN(0.63f, 0.39f, 0.26f, 1.0f);
const D3DXCOLOR ORANGE(1.0f, 0.50f, 0.0f, 1.0f);
const D3DXCOLOR LIGHTBLUE(0.0f, 0.5f, 1.0f, 1.0f);

#define POLLRATE 1
#define TIMERPOLLRATE 0.5

/*---------------------------------------------------------------------------------------------------------*/
/*---------------------------------------------------------------------------------------------------------*/

#if 0 //Included Classes

	RNGen				// Random Number Generator *Singleton*
	CTimer				// Precision Timer
	CMath				// Math functions *Singleton*
	CSystemAnalysis		// Performance monintoring *Singleton*
	CPathing			// 3D Pathing with no A* or Collision (may include both at a later time)
	CConversion			// Conversion Class *Singleton*

#endif

/*---------------------------------------------------------------------------------------------------------*/
/*---------------------------------------------------------------------------------------------------------*/

template <typename TYPE>
void Swap(TYPE& x, TYPE& y)
{
	x ^= y;
	y ^= x;
	x ^= y;
}

/*---------------------------------------------------------------------------------------------------------*/
/*---------------------------------------------------------------------------------------------------------*/

/////////////////////////////////////////////     Class     /////////////////////////////////////////////////
// Name: RNGen
// Author: James Chen
// Created: Friday, January 29, 2010 12:10:04 PM
//
// Purpose: Random Number Generator
//
// Revisions: 
//
/////////////////////////////////////////////////////////////////////////////////////////////////////////////
class RNGen
{
	////////////////////// Singleton Implementation Begins //////////////////////
private:

	RNGen(void);
	RNGen(const RNGen&);
	RNGen& operator =(const RNGen&);
	static RNGen *m_pInstance;
	
	double ReturnValue;
	double Ratio;

	float ReturnValueF;

	double BiasDistance;

	unsigned int RN;
	unsigned int SEED;

	unsigned int BiasSize;

	int MZ;
	int MW;

public:

	virtual ~RNGen(void);
	static RNGen *GetInstance(void);
	static void DeleteInstance(void);
	/////////////////////// Singleton Implementation Ends ///////////////////////

	unsigned int GetLastRN(void)
	{
		return this->RN;
	}

	void Reseed(void);

	bool LoadLastSeed(void);			/* Loads the last saved seed for FASTSEED from text file [8/12/2010 10:43 AM by: James Chen] */
	bool SaveSeed(void);				/* Saves the seed for FASTSEED for future use for debugging purposes or saved game usage [8/12/2010 10:43 AM by: James Chen] */

	//Fast RNGs generate the same numbers every run
	unsigned int FastMW(void);
	unsigned int FastW(void);
	unsigned int FastI(void);

	unsigned int FastSeed(void); // This is a fast implementation that uses random seeds to seed a fast implementation for true random numbers every program call thus unpredictable unless you have the seed values of the program call

	//Slow RNGs are harder to predict
	unsigned int Slow(void);

	double RandD(RNDTYPE TYPE, double LowValue, double HighValue);
	float RandF(RNDTYPE TYPE, float LowValue, float HighValue);

	double RandBiasD(RNDTYPE TYPE, double LowValue, double HighValue, double *Bias);

	D3DX10INLINE D3DXVECTOR3 RandUnitVec3F(RNDTYPE TYPE)
	{
		D3DXVECTOR3 value;

		switch(TYPE)
		{
		case FASTMW:
			{
				value.x = RandF(FASTMW, 0.0f, 1.0f);
				value.y = RandF(FASTMW, 0.0f, 1.0f);
				value.z = RandF(FASTMW, 0.0f, 1.0f);
			}
		case FASTW:
			{
				value.x = RandF(FASTW, 0.0f, 1.0f);
				value.y = RandF(FASTW, 0.0f, 1.0f);
				value.z = RandF(FASTW, 0.0f, 1.0f);
			}
		case FASTI:
			{
				value.x = RandF(FASTI, 0.0f, 1.0f);
				value.y = RandF(FASTI, 0.0f, 1.0f);
				value.z = RandF(FASTI, 0.0f, 1.0f);
			}
		case FASTSEED:
			{
				value.x = RandF(FASTSEED, 0.0f, 1.0f);
				value.y = RandF(FASTSEED, 0.0f, 1.0f);
				value.z = RandF(FASTSEED, 0.0f, 1.0f);
			}
		case SLOW:
			{
				value.x = RandF(SLOW, 0.0f, 1.0f);
				value.y = RandF(SLOW, 0.0f, 1.0f);
				value.z = RandF(SLOW, 0.0f, 1.0f);
			}
		default:
			{

			}
		};

		D3DXVec3Normalize(&value, &value);

		return value;
	}

	//////////////////////////////////////////     Accessors     ////////////////////////////////////////////////
	// Author: James Chen
	// Created: Tuesday, February 02, 2010 9:30:20 AM
	//
	// Purpose: returns the specified type
	//
	/////////////////////////////////////////////////////////////////////////////////////////////////////////////
	inline int& GetSeedValue1(void)
	{
		return MZ;
	}

	inline int& GetSeedValue2(void)
	{
		return MW;
	}

	///////////////////////////////////////////     Mutators     ////////////////////////////////////////////////
	// Author: James Chen
	// Created: Tuesday, February 02, 2010 9:30:29 AM
	//
	// Purpose: sets the class' variables
	//
	/////////////////////////////////////////////////////////////////////////////////////////////////////////////
	inline void SetSeedValue1(int mz)
	{
		this->MZ = mz;
	}

	inline void SetSeedValue2(int mw)
	{
		this->MW = mw;
	}
};

/*---------------------------------------------------------------------------------------------------------*/
/*---------------------------------------------------------------------------------------------------------*/


/////////////////////////////////////////////     Class     /////////////////////////////////////////////////
// Name: CTimer
// Author: James Chen
// Created: Thursday, January 29, 2010 12:10:04 PM
//
// Purpose: Timer class that keeps track of the current time
//
// Revisions: 
//
/////////////////////////////////////////////////////////////////////////////////////////////////////////////
class CTimer
{
private:

	vector<double> m_vProfiler;				
	vector<double>::iterator ITERATOR;

	LARGE_INTEGER m_liTickFrequency;		/* The tick frequency */
	double m_dTimeStart;					/* The start time */
	double m_dTimeDelta;					/* The change in time since the last update */
	double m_dAccumulation;					/* Quantifies Work Time [8/13/2010 9:40 AM by: James Chen] */
	double m_dRunTime;						/* The run time of the timer without including the paused time [8/13/2010 9:41 AM by: James Chen] */
	int m_nFPS;								/* Updates per second */
	bool m_bPaused;							/* This allows the timer to be paused [5/9/2010 11:42 PM by: James Chen] */

public:

	CTimer(void);
	virtual ~CTimer(void);

	void Initialize(void);
	void Update(void);
	double GetTimeSinceStart(void);				/* This function will include Paused time. [5/10/2010 12:42 AM by: James Chen] */
	double GetAverageWorkTime(void);			/* This function will calculate the average time it takes to complete a certain section of code [8/12/2010 9:48 AM by: James Chen] */
	bool GetAverageWorkTimeByCount(unsigned int Count, double &average); /* This function will produce the average work time of code after the counter has been reached [8/12/2010 9:49 AM by: James Chen] */

	inline double GetDeltaTime(void)
	{
		return this->m_dTimeDelta < 0.0 ? 0.0 : this->m_dTimeDelta;  /* If the application gets bumped to another processor delta time can be negative [8/13/2010 9:38 AM by: James Chen] */
	}

	inline double GetRunTime(void)
	{
		return this->m_dRunTime;
	}

	inline int GetFPS(void)
	{
		return this->m_nFPS;
	}

	inline void Pause(void)
	{
		this->m_bPaused = true;
	}

	inline void Unpause(void)
	{
		this->m_bPaused = false;
	}

	inline void AddWorkTime(double time)
	{
		this->m_vProfiler.push_back(time);
	}
};

/*---------------------------------------------------------------------------------------------------------*/
/*---------------------------------------------------------------------------------------------------------*/


/////////////////////////////////////////////     Class     /////////////////////////////////////////////////
// Name: CMath
// Author: James Chen
// Created: Wednesday, February 03, 2010 3:07:43 PM
//
// Purpose: Math helper functions
//
// Revisions: 
//
/////////////////////////////////////////////////////////////////////////////////////////////////////////////
class CMath
{
	////////////////////// Singleton Implementation Begins //////////////////////
private:

	CMath(void);
	CMath(const CMath&);
	CMath& operator =(const CMath&);
	static CMath *m_pInstance;

	float m_fTheta;

public:

	virtual ~CMath(void);
	static CMath *GetInstance(void);
	static void DeleteInstance(void);
	/////////////////////// Singleton Implementation Ends ///////////////////////

	float LinearInterpolationF(const float &Min, const float &Max, const float &Progression);
	double LinearInterpolationD(const double &Min, const double &Max, const double &Progression);

	D3DXVECTOR3 Slerp3D(const D3DXVECTOR3 &start, const D3DXVECTOR3 &end, const float &Progression);
	D3DXVECTOR2 Slerp2D(const D3DXVECTOR2 &start, const D3DXVECTOR2 &end, const float &Progression);

	double DistanceFast(const D3DXVECTOR3 &start, const D3DXVECTOR3 &end);
	double DistanceTrue(const D3DXVECTOR3 &start, const D3DXVECTOR3 &end);
	double DistanceFast(const double &xDiff, const double &yDiff, const double &zDiff);
	double DistanceTrue(const double &xDiff, const double &yDiff, const double &zDiff);
};

/*---------------------------------------------------------------------------------------------------------*/
/*---------------------------------------------------------------------------------------------------------*/


/////////////////////////////////////////////     Class     /////////////////////////////////////////////////
// Name: CSystemAnalysis
// Author: James Chen
// Created: Saturday, April 24, 2010 10:45:35 PM
//
// Purpose: Performs anaylysis on the system
//
// Revisions: 
//
/////////////////////////////////////////////////////////////////////////////////////////////////////////////
class CSystemAnalysis
{
	////////////////////// Singleton Implementation Begins //////////////////////
private:

	CSystemAnalysis(void);
	CSystemAnalysis(const CSystemAnalysis&);
	CSystemAnalysis& operator =(const CSystemAnalysis&);
	static CSystemAnalysis *m_pInstance;

	//CPU Polling
	bool					m_canReadCpu;
	HQUERY					m_queryHandle;
	HCOUNTER				m_counterHandle;
	unsigned long			m_ulLastSampleTime;
	PDH_FMT_COUNTERVALUE	m_value;
	long					m_cpuUsage;

	//Memory Polling
	MEMORYSTATUSEX			memstat;

public:

	virtual ~CSystemAnalysis(void);
	static CSystemAnalysis *GetInstance(void);
	static void DeleteInstance(void);
	/////////////////////// Singleton Implementation Ends ///////////////////////

	void Initialize(void);
	void Shutdown(void);
	void Update(void);
	int GetCpuUsage(void);
	double GetMemUsage(void);


};

/*---------------------------------------------------------------------------------------------------------*/
/*---------------------------------------------------------------------------------------------------------*/


/////////////////////////////////////////////     Class     /////////////////////////////////////////////////
// Name: CPath
// Author: James Chen
// Created: Monday, May 10, 2010 5:24:52 PM
//
// Purpose: Pathing with set waypoints
//
// Revisions: 
//
/////////////////////////////////////////////////////////////////////////////////////////////////////////////
class CPathing
{
private:
	vector<D3DXVECTOR3> m_vPath;

	vector<D3DXVECTOR3>::iterator m_Iterator;
	vector<D3DXVECTOR3>::iterator m_PositionIterator;

	D3DXVECTOR3 *m_pVecPosition;
	D3DXVECTOR3 m_VecPosition;

	PATHTYPE m_nPathType;
	double m_dSpeed;
	double m_dRemainingSpeed;
	double m_dTravelDistance;
	double m_dTotalDistance;
	bool m_bContinuous;
	bool m_bLinked;

public:
	CPathing(void);
	virtual ~CPathing(void);


	void RemoveWaypoint(const int &ArrayPosition);
	void Update(const float &DeltaTime);
	void AddWaypoints(const D3DXVECTOR3 *Waypoints, const int Count);
	void RotateYAxis(const float &angle);
	double CalculateDistance(void);
	void Reset(void);


	void AddWaypoint(const D3DXVECTOR3 &Waypoint)
	{
		this->m_vPath.push_back(Waypoint);

		if(this->m_vPath.size() == 1)
		{
			this->m_PositionIterator = this->m_vPath.begin();
		}
	}

	void KillPath(void)
	{
		this->m_vPath.clear();
	}

	void LinkToPath(D3DXVECTOR3 *positionVector = 0)
	{
		if(positionVector)
		{
			this->m_bLinked = true;

			this->m_pVecPosition = positionVector;

			return;
		}
	}

	void UnlinkToPath()
	{
		this->m_bLinked = false;

		this->m_pVecPosition = 0;
	}

	///////////////////////////////////////////     Mutators     ////////////////////////////////////////////////
	// Author: James Chen
	// Created: Monday, May 10, 2010 6:59:56 PM
	//
	// Purpose: sets the class' variables
	//
	/////////////////////////////////////////////////////////////////////////////////////////////////////////////

	void SetType(PATHTYPE TYPE)
	{
		this->m_nPathType = TYPE;
	}

	void SetSpeed(const double &Speed)
	{
		this->m_dSpeed = Speed;
	}

	void SetContinuous(const bool &Continuous)
	{
		this->m_bContinuous = Continuous;
	}

	//////////////////////////////////////////     Accessors     ////////////////////////////////////////////////
	// Author: James Chen
	// Created: Monday, May 10, 2010 6:59:47 PM
	//
	// Purpose: returns the specified type
	//
	/////////////////////////////////////////////////////////////////////////////////////////////////////////////

	PATHTYPE GetType(void)
	{
		return this->m_nPathType;
	}

	double GetTotalDistance(void)
	{
		return this->m_dTotalDistance;
	}

	D3DXVECTOR3 GetPosition(void)
	{
		return this->m_VecPosition;
	}
};

/*---------------------------------------------------------------------------------------------------------*/
/*---------------------------------------------------------------------------------------------------------*/


/////////////////////////////////////////////     Class     /////////////////////////////////////////////////
// Name: CConversion
// Author: James Chen
// Created: Saturday, May 15, 2010 1:04:09 PM
//
// Purpose: This stores all the conversions that are need
//
// Revisions: 
//
/////////////////////////////////////////////////////////////////////////////////////////////////////////////

/* Linear Conversions [5/15/2010 1:10 PM by: James Chen] */
#define MetrToFt 3.2808399
#define FtToMetr 0.3048

#define MiToMetr 1609.344
#define MetrToMi 0.000621371192

#define MiToYard 1760
#define YardToMi 0.000568181818

#define MetrToYard 1.0936133
#define YardToMetr 0.9144

#define InchToCM 2.54
#define CMToInch 0.393700787

#define MiToKM 1.6094
#define KMToMi 0.62137

#define AUToMi 92955887.6
#define MiToAU 0.000000107577922239

#define LightyearToMi 5878499810000


/* Weight Conversions [5/15/2010 1:10 PM by: James Chen] */
#define KgToLb 2.20462262
#define LbToKg 0.45359237

#define GramToLb 0.00220462262
#define LbToGram 453.59237

#define GrnToGram 0.06479891
#define GramToGrn 15.4323584

#define LbToGrn 7000
#define GrnToLb 0.000142857143

#define GrainToKg 0.00006479891
#define KgToGrain 15432.3584


/* Speed Conversions [5/15/2010 1:10 PM by: James Chen] */
#define SpeedOfLightMPH 670616629
#define SpeedOfLightMeterPerSec 299792458

#define KnotToMPH 1.15077945
#define MPHToKnot 0.868976242

#define MachToMPH 761.207051
#define MPHToMach 0.001313703018

#define MachToMeterPerSecond 340.29
#define MeterPerSecondToMach 0.002938669958

#define MachToFeetPerSecond 1116.43701
#define FeetPerSecondToMach 0.000895706601486


class CConversion
{
	////////////////////// Singleton Implementation Begins //////////////////////
private:

	CConversion(void);
	CConversion(const CConversion&);
	CConversion& operator =(const CConversion&);
	static CConversion *m_pInstance;

public:

	virtual ~CConversion(void);
	static CConversion *GetInstance(void);
	static void DeleteInstance(void);
	/////////////////////// Singleton Implementation Ends ///////////////////////

	double GoldenRatio(void)
	{
		return GOLDENRATIO;
	}

	/* Linear Conversions [5/15/2010 1:10 PM by: James Chen] */
	double FeetToMeter(double value, bool inverse = false);
	double YardToMeter(double value, bool inverse = false);
	double YardToMile(double value, bool inverse = false);
	double MeterToMile(double value, bool inverse = false);
	double KilometerToMile(double value, bool inverse = false);
	double CentimeterToInch(double value, bool inverse = false);

	/* Weight Conversions [5/15/2010 1:10 PM by: James Chen] */
	double PoundToKilogram(double value, bool inverse = false);
	double GramToPound(double value, bool inverse = false);
	double GrainToGram(double value, bool inverse = false);
	double PoundToGrain(double value, bool inverse = false);
	double GrainToKilogram(double value, bool inverse = false);

	/* Speed Conversions [5/15/2010 1:10 PM by: James Chen] */
	double FeetPerSecToMilePerHour(double value, bool inverse = false);
	double FeetPerSecToMach(double value, bool inverse = false);
	double MeterPerSecToMilePerHour(double value, bool inverse = false);
	double SpeedOfLightInMeterPerSec(bool inverse = false);
	double SpeedOfLightInMilePerHour(bool inverse = false);

};

/*---------------------------------------------------------------------------------------------------------*/
/*---------------------------------------------------------------------------------------------------------*/


/////////////////////////////////////////////     Class     /////////////////////////////////////////////////
// Name: CRunManager
// Author: James Chen
// Created: Tuesday, August 17, 2010 10:54:12 PM
//
// Purpose: Currently this keeps count of how many times the program has been run
//
// Revisions: 
//
/////////////////////////////////////////////////////////////////////////////////////////////////////////////
class CRunManager
{
	////////////////////// Singleton Implementation Begins //////////////////////
private:

	char			*m_cpFileLocation;

	ifstream		fin;
	ofstream		fout;

	unsigned int	m_uiCount;
	bool			m_bCounted;

	CRunManager(void);
	CRunManager(const CRunManager&);
	CRunManager& operator =(const CRunManager&);
	static CRunManager *m_pInstance;

public:

	virtual ~CRunManager(void);
	static CRunManager *GetInstance(void);
	static void DeleteInstance(void);
	/////////////////////// Singleton Implementation Ends ///////////////////////

	void Initialize(char *FileLocation);
	void CountRun();
	unsigned int GetCount(void);
};


/*---------------------------------------------------------------------------------------------------------*/
/*---------------------------------------------------------------------------------------------------------*/

#if 0

	DIK_0,
    DIK_1,
    DIK_2,
    DIK_3,
    DIK_4,
    DIK_5,
    DIK_6,
    DIK_7,
    DIK_8,
    DIK_9,
    DIK_A,
    DIK_ABNT_C1,
    DIK_ABNT_C2,
    DIK_ADD,
    DIK_APOSTROPHE,
    DIK_APPS,
    DIK_AT,
    DIK_AX,
    DIK_B,
    DIK_BACK,
    DIK_BACKSLASH,
    DIK_C,
    DIK_CALCULATOR,
    DIK_CAPITAL,
    DIK_COLON,
    DIK_COMMA,
    DIK_CONVERT,
    DIK_D,
    DIK_DECIMAL,
    DIK_DELETE,
    DIK_DIVIDE,
    DIK_DOWN,
    DIK_E,
    DIK_END,
    DIK_EQUALS,
    DIK_ESCAPE,
    DIK_F,
    DIK_F1,
    DIK_F2,
    DIK_F3,
    DIK_F4,
    DIK_F5,
    DIK_F6,
    DIK_F7,
    DIK_F8,
    DIK_F9,
    DIK_F10,
    DIK_F11,
    DIK_F12,
    DIK_F13,
    DIK_F14,
    DIK_F15,
    DIK_G,
    DIK_GRAVE,
    DIK_H,
    DIK_HOME,
    DIK_I,
    DIK_INSERT,
    DIK_J,
    DIK_K,
    DIK_KANA,
    DIK_KANJI,
    DIK_L,
    DIK_LBRACKET,
    DIK_LCONTROL,
    DIK_LEFT,
    DIK_LMENU,
    DIK_LSHIFT,
    DIK_LWIN,
    DIK_M,
    DIK_MAIL,
    DIK_MEDIASELECT,
    DIK_MEDIASTOP,
    DIK_MINUS,
    DIK_MULTIPLY,
    DIK_MUTE,
    DIK_MYCOMPUTER,
    DIK_N,
    DIK_NEXT,
    DIK_NEXTTRACK,
    DIK_NOCONVERT,
    DIK_NUMLOCK,
    DIK_NUMPAD0,
    DIK_NUMPAD1,
    DIK_NUMPAD2,
    DIK_NUMPAD3,
    DIK_NUMPAD4,
    DIK_NUMPAD5,
    DIK_NUMPAD6,
    DIK_NUMPAD7,
    DIK_NUMPAD8,
    DIK_NUMPAD9,
    DIK_NUMPADCOMMA,
    DIK_NUMPADENTER,
    DIK_NUMPADEQUALS,
    DIK_O,
    DIK_OEM_102,
    DIK_P,
    DIK_PAUSE,
    DIK_PERIOD,
    DIK_PLAYPAUSE,
    DIK_POWER,
    DIK_PREVTRACK,
    DIK_PRIOR,
    DIK_Q,
    DIK_R,
    DIK_RBRACKET,
    DIK_RCONTROL,
    DIK_RETURN,
    DIK_RIGHT,
    DIK_RMENU,
    DIK_RSHIFT,
    DIK_RWIN,
    DIK_S,
    DIK_SCROLL,
    DIK_SEMICOLON,
    DIK_SLASH,
    DIK_SLEEP,
    DIK_SPACE,
    DIK_STOP,
    DIK_SUBTRACT,
    DIK_SYSRQ,
    DIK_T,
    DIK_TAB,
    DIK_U,
    DIK_UNDERLINE,
    DIK_UNLABELED,
    DIK_UP,
    DIK_V,
    DIK_VOLUMEDOWN,
    DIK_VOLUMEUP,
    DIK_W,
    DIK_WAKE,
    DIK_WEBBACK,
    DIK_WEBFAVORITES,
    DIK_WEBFORWARD,
    DIK_WEBHOME,
    DIK_WEBREFRESH,
    DIK_WEBSEARCH,
    DIK_WEBSTOP,
    DIK_X,
    DIK_Y,
    DIK_YEN,
    DIK_Z

	DIK_BACKSPACE		DIK_BACK		BACKSPACE  
	DIK_CAPSLOCK		DIK_CAPITAL		CAPS LOCK  
	DIK_CIRCUMFLEX		DIK_PREVTRACK	On Japanese keyboard  
	DIK_DOWNARROW		DIK_DOWN		On arrow keypad  
	DIK_LALT			DIK_LMENU		Left ALT  
	DIK_LEFTARROW		DIK_LEFT		On arrow keypad  
	DIK_NUMPADMINUS		DIK__SUBTRACT	MINUS SIGN (-) on numeric keypad  
	DIK_NUMPADPERIOD	DIK_DECIMAL		PERIOD (decimal point) on numeric keypad  
	DIK_NUMPADPLUS		DIK_ADD			PLUS SIGN (+) on numeric keypad  
	DIK_NUMPADSLASH		DIK__DIVIDE		Forward slash (/) on numeric keypad  
	DIK_NUMPADSTAR		DIK_MULTIPLY	Asterisk (*) on numeric keypad  
	DIK_PGDN			DIK_NEXT		On arrow keypad  
	DIK_PGUP			DIK_PRIOR		On arrow keypad  
	DIK_RALT			DIK_RMENU		Right ALT  
	DIK_RIGHTARROW		DIK_RIGHT		On arrow keypad  
	DIK_UPARROW			DIK_UP			On arrow keypad  


#endif

typedef unsigned char UCHAR;
typedef unsigned char BYTE;

//	Defines for the Mouse.
enum MouseAxises  { XAXIS = 1, YAXIS, ZAXIS, };
enum MouseButtons { M_BUTTON_LEFT = 0, M_BUTTON_RIGHT, M_BUTTON_MIDDLE, M_BUTTON_BACK, };

#define BUFFER_SIZE 10										//	Arbitrary number of buffer element for Buffered Input.

/////////////////////////////////////////////     Class     /////////////////////////////////////////////////
// Name: CDXInput
// Author: James Chen
// Created: Tuesday, August 10, 2010 3:27:56 PM
//
// Purpose: Input Device message handling
//
// Revisions: 
//
/////////////////////////////////////////////////////////////////////////////////////////////////////////////
class CDXInput
{
	////////////////////// Singleton Implementation Begins //////////////////////
private:

	CDXInput(void);
	CDXInput(const CDXInput&);
	CDXInput& operator =(const CDXInput&);
	static CDXInput *m_pInstance;

public:

	virtual ~CDXInput(void);
	static CDXInput *GetInstance(void);
	static void DeleteInstance(void);
	/////////////////////// Singleton Implementation Ends ///////////////////////

private:
	LPDIRECTINPUT8		 m_lpDIObject;					//	Direct Input COM Object.
	LPDIRECTINPUTDEVICE8 m_lpDIKey;						//	Direct Input Device for the Keyboard.
	LPDIRECTINPUTDEVICE8 m_lpDIMouse;					//	Direct Input Device for the Mouse.
	DIDEVICEOBJECTDATA   m_didodKey[BUFFER_SIZE];		//	Receives buffered data for the Keyboard.
	DIDEVICEOBJECTDATA	 m_didodMouse[BUFFER_SIZE];		//	Receives buffered data for the Mouse.

	bool	  m_bExclusive;								//	Determines the cooperation level for the devices.
	char	  m_szBuffer[128];							//	For Error Tracking.
	HKL	 	  m_keyLayout;								//	The Keyboard Layout.
	HWND	  m_hWnd;									//	Main Window Handle.
	HINSTANCE m_hInstance;								//	Main Application Instance.

	UCHAR		  m_ucKeyState[256];					//	Holds Keyboard Data.
	bool		  m_bKeysPressed[256];					//	Used for BufferedKeyEx.
	BYTE		  m_ucAsciiVals[256];					//	Gonna hold the DAMN ascii value of a given key.
	DIMOUSESTATE2 m_diMouseState;						//	Holds Mouse	Data.
	bool		  m_bMouseButtons[8];					//	Used for OnMouseButtonRelease Method.
	DWORD		  m_dwKeyElements;						//	Number of Elements in the Buffer for the Keyboard.
	DWORD		  m_dwMouseElements;					//	Number of Elements in the Buffer for the Mouse.

public:
	
	bool InitDevices(HWND hWnd, HINSTANCE hMainInstance, bool bExclusive = false);

	bool InitKeyboard(HWND hWnd, HINSTANCE hMainInstance, bool bExclusive = false);
	bool InitMouse(HWND hWnd, HINSTANCE hMainInstance, bool bExclusive = false);

	void ShutdownDirectInput(void);

	bool ReadDevices(void);

	bool ReadKeyboard(void);
	bool ReadBufferedKeyboard(void);
	bool GetKey(UCHAR ucKey);
	char CheckKeys(void);
	char CheckBufferedKeys(void);
	bool GetBufferedKey(UCHAR ucKey);
	bool GetBufferedKeyEx(UCHAR ucKey);

	bool ReadMouse(void);
	bool ReadBufferedMouse(void);
	bool OnMouseButtonRelease(BYTE mButton);
	bool GetMouseButton(BYTE mButton);
	bool GetBufferedMouseButton(BYTE mButton);
	LONG GetMouseAxis(LONG lAxis);

};

/*---------------------------------------------------------------------------------------------------------*/
/*---------------------------------------------------------------------------------------------------------*/

#if FMODUSAGE

/////////////////////////////////////////////     Class     /////////////////////////////////////////////////
// Name: CSoundManager
// Author: James Chen
// Created: Wednesday, August 25, 2010 7:20:18 PM
//
// Purpose: Used for CSoundManager
//
// Revisions: 
//
/////////////////////////////////////////////////////////////////////////////////////////////////////////////

class CSound
{
public:

	FMOD::Sound *sound;
	FMOD::Channel *channel;

	float volume;

public:
	CSound(float volume = 1.0f);
	virtual ~CSound(void);

	FMOD::Sound **GetSound();
	FMOD::Channel **GetChannel();

	void SetVolume(float volume);
	float GetVolume();
};

/*---------------------------------------------------------------------------------------------------------*/
/*---------------------------------------------------------------------------------------------------------*/


/////////////////////////////////////////////     Class     /////////////////////////////////////////////////
// Name: CSoundManager
// Author: James Chen
// Created: Wednesday, August 25, 2010 7:25:33 PM
//
// Purpose: This is the sound manager
//
// Revisions: 
//
/////////////////////////////////////////////////////////////////////////////////////////////////////////////
class CSoundManager
{
	////////////////////// Singleton Implementation Begins //////////////////////
private:

	CSoundManager(void);
	CSoundManager(const CSoundManager&);
	CSoundManager& operator =(const CSoundManager&);
	static CSoundManager *m_pInstance;

public:

	virtual ~CSoundManager(void);
	static CSoundManager *GetInstance(void);
	static void DeleteInstance(void);
	/////////////////////// Singleton Implementation Ends ///////////////////////

private:

	vector<CSound *> sounds;
	vector<FMOD::ChannelGroup *> ChannelGroups;

	FMOD::System *system;
	FMOD_RESULT result;

	int counter;

	float pitch;

public:

	void Init();
	void Update();
	void CleanUp();

	int AddSound(const char *name, FMOD_MODE Type);
	void PlaySound(unsigned int id);

};

/*---------------------------------------------------------------------------------------------------------*/
/*---------------------------------------------------------------------------------------------------------*/

#endif